﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using dotMailer.Sdk;
using dotMailer.Sdk.AddressBook;
using dotMailer.Sdk.Collections;
using dotMailer.Sdk.Contacts.Importing;
using dotMailer.Sdk.Exceptions;
using dotMailer.Sdk.Interfaces;
using Google.GData.Contacts;

namespace ImportGoolgeContacts
{
    public partial class FrmMain : Form
    {
        private const string AppTitle = "dotMailer Google Contact Importer";
        private DmService _api;

        //-----------------------------------------------------------------------
        public FrmMain()
        {
            InitializeComponent();

            Text = AppTitle;


            gpGoogle.Enabled = false;
            gpDotmailer.Enabled = false;
        }

        //----------------------------------------------------------------------------------------------
        public override sealed string Text
        {
            get { return base.Text; }
            set { base.Text = value; }
        }

        //----------------------------------------------------------------------------------------------
        /// <summary>
        /// As a message to the information list box
        /// </summary>
        /// <param name="message"></param>
        /// <param name="args"></param>
        private void AddInfo(string message, params object[] args)
        {
            lstInfo.Items.Insert(0, string.Format(message, args));
            Application.DoEvents();
        }

        //----------------------------------------------------------------------------------------------
        /// <summary>
        /// Displays error message
        /// </summary>
        /// <param name="exception"></param>
        private void DisplayException(DmException exception)
        {
            MessageBox.Show(exception.ToString(), AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }

        //-----------------------------------------------------------------------------------------------
        /// <summary>
        /// Creates instance for the DmService, the first time this is called, it creates the DmService,
        /// which in turn validates the API username and password.
        /// 
        /// Subsequent calls, just fall through as the _api variable will not be null
        /// </summary>
        /// <returns></returns>
        private void CheckCreateDmService()
        {
            if (_api == null)
            {
                if (!string.IsNullOrEmpty(txtApiUsername.Text) && !string.IsNullOrEmpty(txtApiPassword.Text))
                {
                    try
                    {
                        _api = DmServiceFactory.Create(txtApiUsername.Text, txtApiPassword.Text);
                    }
                    catch (DmException e)
                    {
                        if (e is DmServiceNotValidException)
                        {
                            MessageBox.Show("Please check dotMailer credentials", AppTitle, MessageBoxButtons.OK,
                                            MessageBoxIcon.Exclamation);
                        }
                        else
                        {
                            DisplayException(e);
                        }
                    }
                }
                else
                {
                    MessageBox.Show("Please provide dotMailer API credentials", AppTitle,
                                    MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

                }
            }
        }

        //-----------------------------------------------------------------------
        /// <summary>
        /// Test Connection button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CmdDmTestClick(object sender, EventArgs e)
        {
            try
            {
                Cursor.Current = Cursors.WaitCursor;
                DmServiceFactory.Create(txtApiUsername.Text, txtApiPassword.Text, true);  // connect via http

                txtApiPassword.ForeColor = Color.Black;
                txtApiUsername.ForeColor = Color.Black;

                Cursor.Current = Cursors.Default;
                MessageBox.Show("dotMailer connection successful", AppTitle, MessageBoxButtons.OK,
                            MessageBoxIcon.Information);

                gpGoogle.Enabled = true;
            }
            catch (DmException)
            {
                txtApiPassword.ForeColor = Color.Red;
                txtApiUsername.ForeColor = Color.Red;

                Cursor.Current = Cursors.Default;
                MessageBox.Show("dotMailer connection FAILED", AppTitle, MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        //-----------------------------------------------------------------------
        private void TxtApiPasswordTextChanged(object sender, EventArgs e)
        {
            gpGoogle.Enabled = true;
        }

        //-----------------------------------------------------------------------
        private void TxtGoolgePasswordTextChanged(object sender, EventArgs e)
        {
            gpDotmailer.Enabled = true;
        }

        //-----------------------------------------------------------------------
        private void LstAddressBookClick(object sender, EventArgs e)
        {
            cmdImport.Enabled = true;
        }

        //-----------------------------------------------------------------------
        /// <summary>
        /// Create address book button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CmdCreateAddressBookClick(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(txtAddressBook.Text.Trim()))
            {
                CheckCreateDmService();

                try
                {
                    string addressBookName = txtAddressBook.Text.Trim();

                    // create the address book
                    DmAddressBook book = _api.AddressBookFactory.CreateAddressBook(addressBookName);

                    if (book != null && book.Id > 0)
                    {
                        // re-populate the address book list
                        CmdPopulateClick(this, null);

                        // find the address book we just created
                        if (lstAddressBook.Items.Contains(book.Name))
                        {
                            for (int i = 0; i < lstAddressBook.Items.Count; i++)
                            {
                                if (lstAddressBook.Items[i].ToString() == book.Name)
                                {
                                    txtAddressBook.Text = "";
                                    lstAddressBook.SelectedIndex = i;
                                    cmdImport.Enabled = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                catch (DmException ex)
                {
                    DisplayException(ex);
                }
            }
            else
            {
                MessageBox.Show("Please provide a name for the new address book", AppTitle, MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
            }
        }

        //-----------------------------------------------------------------------
        /// <summary>
        /// Populate address book list button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CmdPopulateClick(object sender, EventArgs e)
        {
            CheckCreateDmService();

            lstAddressBook.Items.Clear();

            try
            {
                DmAddressBookCollection books = _api.AddressBookFactory.ListAddressBooks();

                if (books != null)
                {
                    foreach (DmAddressBook book in books)
                    {
                        lstAddressBook.Items.Add(book.Name);
                    }
                }
            }
            catch (DmException ex)
            {
                DisplayException(ex);
            }
        }

        //-----------------------------------------------------------------------
        private void TxtAddressBookTextChanged(object sender, EventArgs e)
        {
            if (lstAddressBook.Items.Count > 0 && lstAddressBook.SelectedIndex > -1)
            {
                lstAddressBook.SelectedIndex = -1;
            }
        }

        //-----------------------------------------------------------------------
        /// <summary>
        /// Import contacts button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CmdImportClick(object sender, EventArgs e)
        {
            if (lstAddressBook.SelectedIndex > -1)
            {
                // UI work
                cmdCreateAddressBook.Enabled = false;
                cmdPopulate.Enabled = false;
                cmdImport.Enabled = false;
                lstInfo.Items.Clear();

                string addressBookName = lstAddressBook.Items[lstAddressBook.SelectedIndex].ToString();
                CheckCreateDmService();
                try
                {
                    List<DotMailerGoogleContact> googleContacts = new List<DotMailerGoogleContact>();

                    // get the address book we are going to use
                    DmAddressBook addressBook = _api.AddressBookFactory.GetAddressBookByName(addressBookName);

                    AddInfo("Importing to {0} [{1}]", addressBook.Name, addressBook.Id);

                    // create the google interface
                    ContactsService contactsService = new ContactsService("dotMailer-GoogleContactsImportDemo-v1");
                    contactsService.setUserCredentials(txtGoogleUsername.Text, txtGoolgePassword.Text);

                    AddInfo("Querying Google");

                    // query google
                    ContactsFeed googleFeed =
                        contactsService.Query(new ContactsQuery(ContactsQuery.CreateContactsUri("default")));

                    if (googleFeed != null)
                    {
                        googleContacts.AddRange(from ContactEntry contact in googleFeed.Entries
                                                select new DotMailerGoogleContact(_api.ContactFactory.GetDefaultEmptyDataFieldValues())
                                                {
                                                    Name = contact.Title.Text,
                                                    EmailAddress1 = contact.Emails.Count >= 1 ? contact.Emails[0].Address : "",
                                                    EmailAddress2 = contact.Emails.Count >= 2 ? contact.Emails[1].Address : "",
                                                    Details = contact.Content.Content
                                                });

                        // now we have a list of google contacts - build a list of contacts
                        // that we can actually use

                        AddInfo("Got {0} contacts", googleContacts.Count);

                        // we are also going to import the contacts into the address book, using the 
                        // least amount of api calls, as dotMailer has a limit.
                        List<IDmContact> contactsToImport = googleContacts.Where(contact => contact.Valid).Cast<IDmContact>().ToList();

                        AddInfo("  {0} can be used", contactsToImport.Count);

                        // import and wait for the import to complete
                        // we'll use the default import options
                        ImportContactOptions options = new ImportContactOptions
                                                           {SaveCsvPath = @"c:\temp\csv", SaveCsv = true};

                        ImportContactResult importResult =
                            _api.AddressBookFactory.ImportContactsIntoAddressBook(options,addressBook.Id, contactsToImport);
                        AddInfo("Contacts uploaded");

                        // wait for the import to complete
                        ImportWatcher importWatcher = new ImportWatcher(_api, importResult);
                        importWatcher.Watch();

                        AddInfo("Import is complete");

                        // display results

                        AddInfo("Added {0} contacts", importResult.ImportReport.NewContacts);
                        AddInfo("Updated {0} contacts", importResult.ImportReport.UpdatedContacts);
                        AddInfo("{0} Api methods called", DmServiceFactory.NumberOfWebServiceCalls );
                    }
                }
                catch (DmException ex)
                {
                    DisplayException(ex);
                }
                finally
                {
                    cmdCreateAddressBook.Enabled = true;
                    cmdPopulate.Enabled = true;
                    cmdImport.Enabled = true;
                }
            }
            else
            {
                MessageBox.Show("Please select an Address Book", AppTitle, MessageBoxButtons.OK,
                                MessageBoxIcon.Exclamation);
            }
        }
    }
}
